<template>
  <div class="developer">
    <je-panel>
      <je-panel-item>
        <je-tree
          ref="treeview"
          class="table-treeView"
          draggable
          :tree-config="{
            trigger: 'cell-dblclick',
            rowField: 'id',
            parentField: 'parent',
            checkbox: true,
          }"
          :loading="loading"
          size="mini"
          :data="treeData"
          @current-change="handlerSelect"
          @before-drop="beforedrop"
          @search-select="doSearchChange"
          @drop="drop"
        >
          <template #nodeIcon="{ row }">
            <i
              v-if="row.bean.ROLE_TYPE_CODE === 'folder' && row.children.length === 0"
              class="is--folder fas fa-folder"
            ></i>
          </template>
          <!-- eslint-disable-next-line -->
         <!--  <template #action="options">
            <je-menu :selectable="false">
              <template v-if="options.row.bean.ROLE_TYPE_CODE === 'folder'">
                <je-menu-item
                  v-for="key in menuArray"
                  :key="key.id"
                  @click="menuClickEvent(key.label, options)"
                  ><i :class="key.icon"></i>&nbsp;&nbsp;{{ key.label }}</je-menu-item
                >
              </template>
              <template v-else>
                <je-menu-item
                  v-for="key in menuList"
                  :key="key.id"
                  @click="menuClickEvent(key.label, options)"
                  ><i :class="key.icon"></i>&nbsp;&nbsp;{{ key.label }}</je-menu-item
                >
              </template>
            </je-menu>
          </template> -->
        </je-tree>
      </je-panel-item>
      <je-panel-item region="tbar" v-bind="options.tbar">
        <je-toolbar space="0">
          <!--  <je-button type="text" :disabled="!disabledFile" @click="openFileEvent"
            ><i class="jeicon jeicon-module my-icon"></i>添加分类</je-button
          >
          <je-button type="text" :disabled="!disabledRole" @click="openRoleEvent('添加角色')"
            ><i class="fal fa-user-plus"></i>添加角色</je-button
          >
          <je-button type="text" :disabled="disabledDelEdit" @click="del"
            ><i class="fal fa-user-times"></i>删除</je-button
          > -->
          <je-button type="text" @click="refresh">
            <i class="fal fa-sync"></i>刷新权限缓存
          </je-button>
        </je-toolbar>
      </je-panel-item>
      <!-- <je-panel-item region="bottom" v-bind="options.bottom">
        <je-collapse v-model:activeKey="activeKey" accordion expand-icon-position="right">
          <je-collapse-panel key="1" header="基本信息">
            <div class="content">
              <je-form
                validate-type="tooltip"
                :model="modelRef"
                :label-col="{ span: 6 }"
                :wrapper-col="{ span: 18 }"
                label-align="right"
                :colon="false"
              >
                <je-form-item
                  v-if="remark === 'role'"
                  name="permissionName"
                  label="角色名称"
                  v-bind="validateInfos.permissionName"
                >
                  <je-input v-model:value.trim="modelRef.permissionName" :disabled="disabledRow" />
                </je-form-item>
                <je-form-item v-if="remark === 'role'" label="角色编码" name="code">
                  <je-input v-model:value="modelRef.code" disabled="disabled" />
                </je-form-item>
                <je-form-item
                  v-else
                  name="permissionName"
                  label="分类名称"
                  v-bind="validateInfos.permissionName"
                >
                  <je-input v-model:value.trim="modelRef.permissionName" :disabled="disabledRow" />
                </je-form-item>

                <je-button
                  v-show="btnShow"
                  :disabled="disabledRow"
                  class="btn"
                  type="primary"
                  @click="onSubmit"
                  >保存</je-button
                >
              </je-form>
            </div>
          </je-collapse-panel>
        </je-collapse>
      </je-panel-item> -->
    </je-panel>
    <div v-if="openRole">
      <AddEditRole
        v-model:visible="openRole"
        :current-row="currentRow"
        :mode="mode"
        @AddEditRole="sonCallback"
      />
    </div>
    <div v-if="openFile">
      <AddFile
        v-model:visible="openFile"
        :edit-payload="editPayload"
        :file-mode="fileMode"
        @addFile="sonCallback"
      />
    </div>
    <div v-if="openTransfer">
      <Transfer
        v-model:visible="openTransfer"
        :tree-select-date="treeData"
        :current-row="currentRow"
        @transfer="sonCallback"
      />
    </div>
  </div>
</template>

<script>
  import { defineAsyncComponent, defineComponent, onMounted, reactive, ref, watch } from 'vue';

  import { Button, Panel, Toolbar, Tree, Modal, Form } from '@jecloud/ui';

  import { verifyData } from '@/utils/validate';

  import {
    loadDevRoleTreeApi,
    moveDevRoleApi,
    removeDevFolderApi,
    removeDevRoleApi,
    updateDevFolderApi,
    upDateDevRoleApi,
  } from '@/api';

  import VueEvent from '@/helper/model/event';

  const useForm = Form.useForm;

  export default defineComponent({
    name: 'Developer',
    components: {
      AddEditRole: defineAsyncComponent(() => import('./add-edit-role.vue')),
      AddFile: defineAsyncComponent(() => import('./add-file.vue')),
      Transfer: defineAsyncComponent(() => import('./transfer.vue')),
      JeButton: Button,
      JeToolbar: Toolbar,
      JePanel: Panel,
      JePanelItem: Panel.Item,
      JeTree: Tree,
    },
    setup() {
      // panel配置
      const options = reactive({
        // tabr样式
        tbar: {
          size: 40,
          style: {
            borderRight: '1px solid #e6e6e6',
            borderTop: '1px solid #e6e6e6',
            borderBottom: '1px solid #e6e6e6',
          },
        },
        bottom: {},
      });

      // tree的数据
      const treeData = ref([]);
      const loading = ref(false);
      // 表单数据
      const modelRef = reactive({
        permissionName: '',
        code: '',
      });

      // menu按钮:添加子角色
      const menuList = [
        // { id: '0', label: '添加子角色', icon: 'fal fa-user-friends' },
        { id: '1', label: '删除', icon: 'fal fa-user-times' },
        // { id: '2', label: '编辑', icon: 'jeicon jeicon-from' },
        // { id: '3', label: '转移', icon: 'fal fa-folder-upload' },
      ];
      // menu按钮:添加角色
      const menuArray = [
        { id: '0', label: '添加角色', icon: 'fal fa-user-plus' },
        { id: '1', label: '删除', icon: 'fal fa-user-times' },
        // { id: '2', label: '编辑', icon: 'jeicon jeicon-from' },
        // { id: '3', label: '转移', icon: 'fal fa-folder-upload' },
      ];

      // 获取数据
      let currentMeta = '';
      const getTreeData = (flag) => {
        loading.value = true;
        let params = {};
        if (flag == 'refresh') {
          params = { refresh: '1' };
        }
        // 获取开发者tree
        loadDevRoleTreeApi(params).then((res) => {
          treeData.value = res.children;
          loading.value = false;
          if (flag == 'refresh') {
            Modal.notice('刷新权限缓存成功！', 'success');
          } else if (flag) {
            // 如果是更新
            setTimeout(() => {
              // 模拟点击代码
              current = null;
              const row = treeview.value.getRowById(currentMeta.id);
              treeview.value.setCurrentRow(row);
              handlerSelect({ row });
            }, 200);
          }
        });
      };

      // 初始化数据
      onMounted(() => {
        // 加载权限数据
        getTreeData();
      });

      // 添加和编辑角色dialog
      const openRole = ref(false);
      const mode = ref(null); // 新增还是编辑
      const currentRow = ref({}); // 传给dialog的row
      const openRoleEvent = (val, row) => {
        currentRow.value = current;
        if (row) {
          currentRow.value = row;
        }
        openRole.value = true;
        mode.value = val;
      };

      // 转移弹框打开
      const openTransferEvent = (row) => {
        currentRow.value = current;
        if (row) {
          currentRow.value = row;
        }
        openTransfer.value = true;
      };

      // 添加分类dialog
      const openFile = ref(false);
      // 转移dialog
      const openTransfer = ref(false);
      // 手风琴的显影项
      const activeKey = ref('0');
      // 是角色还是文件夹
      const remark = ref('role');
      //基本信息中的置灰
      const disabledRow = ref(true);

      // 与tree相关按钮是否可操作
      const disabledFile = ref(true); // 文件夹
      const disabledRole = ref(true); // 角色
      const disabledDelEdit = ref(true); // 删除和编辑
      const disabledRolesMove = ref(true); // 子角色和移动
      // 树形结构的点击事件：上方tab的按钮的禁用状态resetDate
      let current = null;
      let meta = null; // 对照组
      let openActiveKey = true; // activeKey开关
      // 点击tree
      const handlerSelect = ({ row }) => {
        // 重置数据
        resetDate();
        // row.id等于current.id,表示取消选择
        if (row.id == current?.id) {
          // 重置数据
          current = null;
          modelRef.permissionName = '';
          modelRef.code = null;
          disabledRow.value = true;
          resetFields();
          // 清空右侧数据
          VueEvent.emit('cleanData');
        } else {
          disabledRow.value = false;
          if (openActiveKey) {
            activeKey.value = '1';
            openActiveKey = false;
          }
          meta = JSON.parse(JSON.stringify(row.text)); // 赋值对比项
          // 当点击文件夹
          if (row.bean.ROLE_TYPE_CODE === 'folder') {
            disabledFile.value = false;
            disabledDelEdit.value = false;
            modelRef.code = null;
            remark.value = 'folder';
            VueEvent.emit('cleanData');
            // 清空右侧数据
          } else {
            // 当点击角色和子角色
            remark.value = 'role';
            modelRef.code = row.code;
            disabledFile.value = false;
            disabledRole.value = false;
            disabledDelEdit.value = false;
            disabledRolesMove.value = false;
          }
          modelRef.permissionName = row.text;
          current = row;
          // 是角色时才展示账号表格
          if (current.bean.ROLE_TYPE_CODE === 'folder') return false;
          VueEvent.emit('showAccount', {
            _id: current.id,
            _type: 'develop',
            _nodeType: 'DEVELOP',
          });
        }
      };

      // 是编辑文件夹还是新增文件夹的标识
      const fileMode = ref('addFile');
      // 编辑需要的参数
      const editPayload = ref(null);
      // 增加文件夹弹框打开
      const openFileCB = () => {
        openFile.value = true;
      };
      // 打开文件夹的事件
      const openFileEvent = () => {
        fileMode.value = 'addFile';
        editPayload.value = null;
        openFileCB();
      };
      const treeview = ref('treeview');
      // 子组件更新数据后的回调
      const sonCallback = (id) => {
        loading.value = true;
        loadDevRoleTreeApi().then((res) => {
          treeData.value = res.children;
          loading.value = false;
          if (id) {
            setTimeout(async () => {
              const row = await treeview.value?.getRowById(id);
              // 展开树
              treeview.value.setTreeExpand4Path({ row, expand: true });
              // tree的所选项
              treeview.value.setSelectRow(row);
              // 代码执行点击
              handlerSelect({ row });
              setTimeout(() => {
                // 滚动
                treeview.value.scrollToRow(row);
              }, 200);
            }, 0);
          } else {
            // 清空数据和高亮
            resetDate();
            treeview.value.clearCurrentRow();
            current = null;
          }
        });
      };

      // 删除节点
      const del = (row) => {
        let folderId = null;
        let remark = null;
        // 删除文件夹
        if (current && row.pointerType) {
          folderId = current.id;
          remark = current.bean.ROLE_TYPE_CODE;
        } else {
          folderId = row.id;
          remark = row.bean.ROLE_TYPE_CODE;
        }
        if (row?.children?.length > 0 || current?.children?.length > 0) {
          return Modal.alert('删除的节点存在下级角色，不允许删除', 'warning');
        }
        if (remark === 'folder') {
          // 删除文件夹
          Modal.confirm('您确定要删除吗？', () => {
            removeDevFolderApi({ folderId }).then((res) => {
              Modal.notice(res, 'success');
              setTimeout(() => {
                getTreeData();
                resetDate();
                disabledRow.value = true;
                current = null;
                VueEvent.emit('cleanData');
              }, 200);
            });
          });
        } else {
          // 删除角色
          Modal.confirm('您确定要删除吗？', () => {
            removeDevRoleApi({ roleId: folderId }).then((res) => {
              Modal.notice(res, 'success');
              setTimeout(() => {
                getTreeData();
                resetDate();
                current = null;
                disabledRow.value = true;
                VueEvent.emit('cleanData');
              }, 200);
            });
          });
        }
      };

      // 重置数据
      const resetDate = () => {
        disabledDelEdit.value = true;
        disabledRole.value = true;
        disabledRolesMove.value = true;
        disabledFile.value = true;
        currentRow.value = null;
        modelRef.code = null;
        modelRef.permissionName = '';
      };

      // 刷新
      const refresh = () => {
        getTreeData('refresh');
        resetDate();
        treeview.value.clearCurrentRow();
        disabledRow.value = true;
        current = null;
        VueEvent.emit('cleanData');
      };

      // tree的mune点击事件
      const menuClickEvent = (val, options) => {
        const { tooltip, row } = options;
        tooltip.visible = false;
        if (val === '删除') {
          del(row);
        } else if (val === '编辑') {
          // 编辑文件夹
          if (row.bean.ROLE_TYPE_CODE === 'folder') {
            fileMode.value = 'editFile';
            editPayload.value = { folderId: row.id, label: row.text };
            openFileCB();
          } else {
            // 编辑角色
            openRoleEvent(val, options.row);
          }
        } else if (val === '转移') {
          openTransferEvent(options.row);
        } else {
          // 角色和子角色
          openRoleEvent(val, options.row);
        }
      };
      // 节点的移动：拖动和转移
      const beforedrop = ({ action, row, $table, target }) => {
        if (row.bean.ROLE_TYPE_CODE === 'folder') {
          // 文件夹只能在一级拖动拖动
          if (action === 'insert') return false;
        } else {
          const parent = $table.getParentRow(row);
          const targetParent = $table.getParentRow(target);
          if (!parent || parent.parent === 'ROOT') {
            // 可以在父集下排序
            if (targetParent?.id === parent?.id && action === 'sort') {
              return true;
            }
            // 可以拖动到一级和文件夹下
            if (target.bean.ROLE_TYPE_CODE === 'role') {
              return false;
            }
          } else {
            // 子角色只可以在父集内部拖动
            if (action === 'insert') return false;
            if (targetParent?.id !== parent?.id) return false;
          }
        }
        return true;
      };

      // 停止拖动
      const drop = function ({ row, $table, action }) {
        // 找到父元素
        const parent = $table.getParentRow(row);
        let index = null;
        if (action === 'sort' && !parent) {
          // 在root下得到index
          index = treeview.value.getRowIndex(row);
        } else {
          index = parent.children.findIndex((item) => {
            return item.id === row.id;
          });
        }
        // 移动后更改数据
        moveDevRoleApi({ roleId: row.id, targetId: parent?.id || 'ROOT', order: index }).then(
          (res) => {
            Modal.notice(res, 'success');
          },
        );
      };

      // 验证规则
      const rulesRef = reactive({
        permissionName: verifyData.title,
      });
      const { resetFields, validate, validateInfos } = useForm(modelRef, rulesRef, {
        // onValidate: (...args) => console.log(...args),
      });
      // 点击保存
      const onSubmit = () => {
        // 校验成功
        validate().then(() => {
          // 表单值发生改变代码继续执行
          if (modelRef.permissionName === meta) return Modal.notice('无数据操作!', 'info');
          meta = JSON.parse(JSON.stringify(modelRef.permissionName)); // 对比项赋值
          // 如是分类
          if (remark.value === 'folder') {
            disabledRow.value = true;
            // 更新分类接口
            updateDevFolderApi({ folderId: current.id, folderName: modelRef.permissionName }).then(
              (res) => {
                Modal.notice(res, 'success');
                setTimeout(() => {
                  currentMeta = JSON.parse(JSON.stringify(current));
                  current = null;
                  getTreeData('flag');
                  disabledRow.value = false;
                }, 50);
              },
            );
          } else {
            disabledRow.value = true;
            // 更新角色
            upDateDevRoleApi({
              roleId: current.id,
              roleName: modelRef.permissionName,
              baseRoleId: current.bean.ROLE_BASE_ID,
              remark: current.bean.ROLE_REMARK,
            }).then((res) => {
              Modal.notice(res, 'success');
              setTimeout(() => {
                currentMeta = JSON.parse(JSON.stringify(current));
                current = null;
                getTreeData('flag');
                disabledRow.value = false;
              }, 50);
            });
          }
        });
        return false;
      };

      // 关闭按钮优化
      const btnShow = ref(false);
      // 根据activeKey的值修改底部框
      watch(
        () => activeKey.value,
        (nv) => {
          if (nv === '1') {
            setTimeout(() => {
              options.bottom.size = 200;
              btnShow.value = true;
            }, 150);
          } else {
            options.bottom.size = 40;
            btnShow.value = false;
          }
        },
      );

      //搜索框选中事件
      const doSearchChange = ({ row }) => {
        handlerSelect({ row });
      };

      return {
        btnShow,
        activeKey,
        modelRef,
        onSubmit,
        resetFields,
        validateInfos,
        options,
        treeData,
        loading,
        openRole,
        openRoleEvent,
        mode,
        openFile,
        openTransfer,
        handlerSelect,
        menuList,
        menuArray,
        disabledDelEdit,
        disabledFile,
        disabledRole,
        disabledRolesMove,
        sonCallback,
        fileMode,
        editPayload,
        del,
        refresh,
        menuClickEvent,
        currentRow,
        openTransferEvent,
        openFileEvent,
        treeview,
        beforedrop,
        drop,
        remark,
        disabledRow,
        doSearchChange,
      };
    },
  });
</script>

<style lang="less" scoped>
  .developer {
    .is--folder {
      color: #ffb04a;
    }
    .fal,
    .jeicon {
      font-size: 14px;
    }
    .my-icon {
      font-size: 13px;
    }
    :deep(.je-toolbar-item .ant-btn) {
      padding: 4px 16px;
    }
    :deep(.table-treeView .je-panel-item-region-default) {
      border-right: 1px solid #e6e6e6;
      // border-top: 1px solid #ffffff;
      padding-bottom: 20px;
    }
    :deep(.table-treeView .je-tree-search-wrapper > *) {
      height: 40px;
      .ant-input-clear-icon {
        top: 10px;
      }
    }
    :deep(.table-treeView .ant-input-affix-wrapper.ant-select-selection-search-input) {
      border-top: 1px solid #ffffff;
      &:hover {
        border-top: 1px solid #5c8dff;
        .ant-input-prefix {
          margin-top: -0.5px;
        }
      }
    }
    :deep(.table-treeView .ant-input-affix-wrapper-focused.ant-select-selection-search-input) {
      border: 1px solid #5c8dff;
    }
    :deep(.je-panel-item-region-bottom) {
      z-index: 9;
    }
    .content {
      padding: 4px;
      height: 130px;
      :deep(.ant-form-item) {
        margin-bottom: 6px;
      }
    }
    :deep(.ant-collapse-header) {
      height: 40px;
      line-height: 15px;
      background: #f7f9fc;
    }
    .btn {
      position: absolute;
      bottom: 20px;
      left: 50%;
      transform: translate(-50%, 0);
    }
  }
</style>
